﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

namespace GGetTestService.Extension
{
    /// <summary>
    /// string扩展方法
    /// </summary>
    public static class StringExtensions
    {
        /// <summary>
        /// 判断当前字符是否为空或者null
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsNullOrEmpty(this string str)
        {
            return string.IsNullOrEmpty(str);
        }

        /// <summary>
        /// 判断当前字符是否是否为空或者null或者含有空格
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsNullOrWhiteSpace(this string str)
        {
            return string.IsNullOrWhiteSpace(str);
        }

        /// <summary>
        /// 从左边截取指定长度的字符
        /// </summary>
        /// <param name="str"></param>
        /// <param name="len"></param>
        /// <returns></returns>
        public static string Left(this string str, int len)
        {
            if (str == null)
            {
                throw new ArgumentNullException(nameof(str));
            }
            if (str.Length < len)
            {
                throw new ArgumentException("len参数不能大于给定字符串的长度");
            }
            return str.Substring(0, len);
        }

        /// <summary>
        /// 从右边截取指定长度的字符
        /// </summary>
        /// <param name="str"></param>
        /// <param name="len"></param>
        /// <returns></returns>
        public static string Right(this string str, int len)
        {
            if (str == null)
            {
                throw new ArgumentNullException(nameof(str));
            }
            if (str.Length < len)
            {
                throw new ArgumentException("len参数不能大于给定字符串的长度");
            }
            return str.Substring(str.Length - len, len);
        }

        /// <summary>
        /// 从string转为enum
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        public static TEntity ToEnum<TEntity>(this string value) where TEntity : struct
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }
            return (TEntity)Enum.Parse(typeof(TEntity), value);
        }

        /// <summary>
        /// 从string转为enum
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="value">当前值</param>
        /// <param name="ignoreCase">是否区分大小写</param>
        /// <returns></returns>
        public static TEntity ToEnum<TEntity>(this string value, bool ignoreCase) where TEntity : struct
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }
            return (TEntity)Enum.Parse(typeof(TEntity), value, ignoreCase);
        }

        /// <summary>
        /// 将由特殊符号拼接成的字符串形式的数据转换为具体类型的数据集合
        /// </summary>
        /// <typeparam name="TType">具体类型</typeparam>
        /// <param name="value"></param>
        /// <param name="separator">分隔符</param>
        /// <returns></returns>
        public static IList<TType> ToList<TType>(this string value, string separator)
        {
            if (value.IsNullOrWhiteSpace())
                return new List<TType>();

            return value.Split(separator.ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
                        .Select(x => ToAnonymousType<TType>(x))
                        .ToList();
        }

        /// <summary>
        /// 构造转换器，将字符串类型的数据转为指定类型
        /// </summary>
        /// <typeparam name="TType"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        private static TType ToAnonymousType<TType>(string value)
        {
            Type type = typeof(TType);
            var converter = TypeDescriptor.GetConverter(type);
            var propertyValue = converter.ConvertFromInvariantString(value);
            return (TType)Convert.ChangeType(propertyValue, type);
        }
    }
}